package com.wg.game.app;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.net.DisconnectReason;
import com.wg.net.operations.InitRequest;
import com.wg.net.peer.AbstractOutboundServerToServerPeer;
import com.wg.net.peer.BasePeer;
import com.wg.net.peer.IManagedPeer;
import com.wg.net.peer.ManagedPeer;
import com.wg.net.protocols.Protocol;
import com.wg.net.session.ISession;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 应用层基础实现类（封装通用连接管理逻辑）
 * <p>
 * 职责：
 * - 实现IApplication接口的通用逻辑
 * - 管理会话计数器（连接数统计）
 * - 处理连接初始化、消息接收、断开等事件的默认逻辑
 * - 提供网络层对端（Peer）和会话的创建接口
 *
 * @author 少爷123
 */
public abstract class BaseApplication implements IApplication {
    private static final Log log = LogFactory.get();
    /**
     * 单例实例（线程安全）
     */
    public static volatile BaseApplication INST;
    /**
     * 运行状态标记
     */
    protected final AtomicBoolean isRunAtomic = new AtomicBoolean(false);
    /**
     * 当前连接数统计
     */
    private final AtomicInteger peerCount = new AtomicInteger(0);

    @Override
    public void onInit(ISession session, byte[] data) {
        if (log.isDebugEnabled()) {
            log.debug("接收到初始化请求 | 连接ID: {}, 数据长度: {}", session.getConnectionId(), data.length);
        }

        try {
            InitRequest request = Protocol.parseInitRequest(data);
            if (request == null) {
                log.warn("初始化请求解析失败 | 连接ID: {}", session.getConnectionId());
                session.close();
                return;
            }

            request.setPeer(session); // 绑定会话到请求对象
            ManagedPeer.create(request, this); // 创建并启动托管对端
        } catch (Exception e) {
            log.error("初始化请求处理异常 | 连接ID: {}", session.getConnectionId(), e);
            session.close(); // 异常时关闭连接
        }
    }

    @Override
    public void onReceive(ISession session, Object userData, byte[] data) {
        if (log.isTraceEnabled()) {
            log.trace("接收到数据 | 连接ID: {}, 数据长度: {}", session.getConnectionId(), data.length);
        }

        try {
            // 校验用户数据类型（必须是IManagedPeer）
            if (!(userData instanceof IManagedPeer)) {
                log.warn("无效的用户数据类型 | 连接ID: {}, 用户数据类型: {}",
                        session.getConnectionId(),
                        userData != null ? userData.getClass().getSimpleName() : "null");
                session.close();
                return;
            }

            IManagedPeer managedPeer = (IManagedPeer) userData;
            managedPeer.applicationOnReceive(data); // 传递数据到应用层处理
        } catch (Exception e) {
            log.error("数据处理异常 | 连接ID: {}", session.getConnectionId(), e);
            session.close(); // 异常时关闭连接
        }
    }

    @Override
    public void onDisconnect(ISession session, Object userData, DisconnectReason reasonCode, String reasonDetail) {
        if (log.isInfoEnabled()) {
            log.info("连接断开 | 连接ID: {}, 原因: {}({})",
                    session.getConnectionId(), reasonCode, reasonDetail);
        }

        try {
            // 校验用户数据类型（必须是IManagedPeer）
            if (!(userData instanceof IManagedPeer)) {
                log.warn("断开事件中用户数据类型无效 | 连接ID: {}, 用户数据类型: {}",
                        session.getConnectionId(),
                        userData != null ? userData.getClass().getSimpleName() : "null");
                return;
            }

            IManagedPeer managedPeer = (IManagedPeer) userData;
            boolean isDisconnectAllowed = managedPeer.applicationOnDisconnect(reasonCode, reasonDetail);

            if (isDisconnectAllowed) {
                decrementPeerCounter(); // 减少连接计数器
                log.debug("连接已释放 | 连接ID: {}", session.getConnectionId());
            }
        } catch (Exception e) {
            log.error("断开事件处理异常 | 连接ID: {}", session.getConnectionId(), e);
        } finally {
            session.setUserData(null); // 清除用户数据防止内存泄漏
        }
    }

    @Override
    public void onOutboundConnectionEstablished(ISession session, Object userData) {
        if (log.isInfoEnabled()) {
            log.info("出站连接建立成功 | 连接ID: {}", session.getConnectionId());
        }

        try {
            if (userData instanceof AbstractOutboundServerToServerPeer) {
                AbstractOutboundServerToServerPeer outboundPeer = (AbstractOutboundServerToServerPeer) userData;
                outboundPeer.onOutboundConnectionEstablished(session); // 传递事件到出站对端
            } else {
                log.error("出站连接建立成功但用户数据类型无效 | 连接ID: {}, 用户数据类型: {}",
                        session.getConnectionId(),
                        userData != null ? userData.getClass().getSimpleName() : "null");
                session.close(); // 类型不匹配时关闭连接
            }
        } catch (Exception e) {
            log.error("出站连接建立成功事件处理异常 | 连接ID: {}", session.getConnectionId(), e);
            session.close();
        }
    }

    @Override
    public void onOutboundConnectionFailed(Object userData, int errorCode, String errorMessage) {
        if (log.isWarnEnabled()) {
            log.warn("出站连接失败 | 错误码: {}, 错误信息: {}", errorCode, errorMessage);
        }

        try {
            if (userData instanceof AbstractOutboundServerToServerPeer) {
                AbstractOutboundServerToServerPeer outboundPeer = (AbstractOutboundServerToServerPeer) userData;
                outboundPeer.onOutboundConnectionFailed(errorCode, errorMessage); // 传递事件到出站对端
            } else {
                log.error("出站连接失败但用户数据类型无效 | 错误码: {}, 错误信息: {}, 用户数据类型: {}",
                        errorCode, errorMessage,
                        userData != null ? userData.getClass().getSimpleName() : "null");
            }
        } catch (Exception e) {
            log.error("出站连接失败事件处理异常 | 错误码: {}", errorCode, e);
        }
    }

    /**
     * 获取当前活跃连接数
     *
     * @return 连接数
     */
    public int getPeerCount() {
        return peerCount.get();
    }

    /**
     * 检查应用是否处于运行状态
     *
     * @return 运行状态（true：运行中；false：已停止）
     */
    public boolean isRunning() {
        return isRunAtomic.get();
    }

    /**
     * 创建网络层对端对象（异步）
     *
     * @param request 初始化请求
     * @return 网络层对端实例
     */
    public BasePeer createPeerInternal(InitRequest request) {
        return createPeer(request);
    }

    /**
     * 增加连接计数器（线程安全）
     */
    public void incrementPeerCounter() {
        int newCount = peerCount.incrementAndGet();
        if (log.isDebugEnabled()) {
            log.debug("连接数增加 | 当前连接数: {}", newCount);
        }
    }

    /**
     * 创建网络层对端（子类需实现具体逻辑）
     *
     * @param initRequest 初始化请求
     * @return 网络层对端实例
     */
    protected abstract BasePeer createPeer(InitRequest initRequest);

    /**
     * 减少连接计数器（线程安全）
     */
    protected void decrementPeerCounter() {
        int newCount = peerCount.decrementAndGet();
        if (log.isDebugEnabled()) {
            log.debug("连接数减少 | 当前连接数: {}", newCount);
        }
    }
}